package com.medvalley.tcm.controller.admin.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.medvalley.tcm.base.BusinessException;
import com.medvalley.tcm.base.Constants;
import com.medvalley.tcm.controller.admin.vo.inputvo.SearchUserInputVo;
import com.medvalley.tcm.controller.admin.vo.outputvo.AppUserInfoOutputVo;
import com.medvalley.tcm.controller.admin.vo.outputvo.PageDataOutputVo;
import com.medvalley.tcm.controller.admin.vo.outputvo.ReportOutputVo;
import com.medvalley.tcm.dao.SickInfoDao;
import com.medvalley.tcm.dao.SickUserDao;
import com.medvalley.tcm.dao.UserInfoDao;
import com.medvalley.tcm.dao.UserInfoDetailDao;
import com.medvalley.tcm.domain.SickAndUser;
import com.medvalley.tcm.domain.SickInfo;
import com.medvalley.tcm.domain.UserInfo;
import com.medvalley.tcm.domain.UserInfoDetail;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author linsong
 * @date 2019/6/19 11:27
 **/
@Service
public class AppUserService {

    @Autowired
    private UserInfoDao userInfoDao;

    @Autowired
    private UserInfoDetailDao userInfoDetailDao;

    @Autowired
    private SickUserDao sickUserDao;

    @Autowired
    private SickInfoDao sickInfoDao;

    public PageDataOutputVo<AppUserInfoOutputVo> pageAppUser(SearchUserInputVo searchUserInputVo) {
        PageDataOutputVo<AppUserInfoOutputVo> pageDataOutputVo = new PageDataOutputVo();
        int pageNo = searchUserInputVo.getPageNo();
        int pageSize = searchUserInputVo.getPageSize();
        List<AppUserInfoOutputVo> appUserInfoOutputVoList = Lists.newArrayList();
        pageDataOutputVo.setPageNo(pageNo);
        pageDataOutputVo.setPageSize(pageSize);
        pageNo = pageNo - 1 < 0 ? 0 : pageNo - 1;
        Pageable pageable = PageRequest.of(pageNo, pageSize, Sort.Direction.DESC, "id");

        Specification<UserInfo> specification = new Specification<UserInfo>() {

            @Override
            public Predicate toPredicate(Root<UserInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list = new ArrayList<Predicate>();
                // 创建时间-  开始
                if (!StringUtils.isEmpty(searchUserInputVo.getBeginDate())) {
                    list.add(criteriaBuilder.greaterThan(root.get("createTime").as(String.class), searchUserInputVo.getBeginDate()));
                }
                // 创建时间-  结束
                if (!StringUtils.isEmpty(searchUserInputVo.getEndDate())) {
                    list.add(criteriaBuilder.lessThan(root.get("createTime").as(String.class), searchUserInputVo.getEndDate()));
                }
                //手机号
                if (!StringUtils.isEmpty(searchUserInputVo.getPhone())) {
                    list.add(criteriaBuilder.equal(root.get("phone").as(String.class), searchUserInputVo.getPhone()));
                }
                int gender = searchUserInputVo.getGender();
                if (gender > 0) {
                    list.add(criteriaBuilder.equal(root.get("gender").as(Integer.class), searchUserInputVo.getGender()));
                }
                String name = searchUserInputVo.getName();
                if (!StringUtils.isEmpty(name)) {
                    list.add(criteriaBuilder.like(root.get("realName").as(String.class), searchUserInputVo.getName() + "%"));
                }
                return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
            }
        };
        Page<UserInfo> pageData = userInfoDao.findAll(specification, pageable);
        if (pageData.hasContent()) {
            List<UserInfo> userInfoList = pageData.getContent();
            List<Long> ids = userInfoList.stream().map(UserInfo::getId).collect(Collectors.toList());
            List<UserInfoDetail> userInfoDetailList = userInfoDetailDao.findAllByUserIdIn(ids);
            Map<Long, UserInfoDetail> userInfoDetailMap = Maps.newHashMap();
            if (!CollectionUtils.isEmpty(userInfoDetailList)) {
                userInfoDetailMap = userInfoDetailList.stream().collect(Collectors.toMap(UserInfoDetail::getUserId, Function.identity()));
            }
            for (UserInfo u : userInfoList) {
                AppUserInfoOutputVo appUserInfoOutputVo = new AppUserInfoOutputVo();
                appUserInfoOutputVo.setId(u.getId());
                appUserInfoOutputVo.setPhone(u.getPhone());
                UserInfoDetail userInfoDetail = userInfoDetailMap.get(u.getId());
                if (userInfoDetail != null) {
                    appUserInfoOutputVo.setHeadIcon(userInfoDetail.getHeadIcon());
                    appUserInfoOutputVo.setName(userInfoDetail.getRealName());
                    appUserInfoOutputVo.setGender(userInfoDetail.getGender());
                } else {
                    appUserInfoOutputVo.setHeadIcon("");
                }
                appUserInfoOutputVo.setCreateTime(DateFormatUtils.format(u.getCreateTime(), Constants.YYYY_MM_DD_HH_MM_SS));
                appUserInfoOutputVoList.add(appUserInfoOutputVo);
            }
        }
        pageDataOutputVo.setTotalElement(pageData.getTotalElements());
        pageDataOutputVo.setTotalPageCount(pageData.getTotalPages());
        pageDataOutputVo.setPageData(appUserInfoOutputVoList);

        return pageDataOutputVo;
    }

    @Transactional
    public void deleteUser(long id) {
        userInfoDao.findById(id).orElseThrow(() -> new BusinessException("查无此人"));
        UserInfoDetail ud = userInfoDetailDao.findOneByUserId(id);
        List<SickAndUser> sickAndUser = sickUserDao.findAllByUserId(id);
        userInfoDao.deleteById(id);
        if (ud != null) {
            userInfoDetailDao.deleteById(ud.getId());
        }
        if (!CollectionUtils.isEmpty(sickAndUser)) {
            sickUserDao.deleteAll(sickAndUser);
        }
    }

    public List<ReportOutputVo> findReportById(long userId) {
        UserInfo userInfo = userInfoDao.findById(userId).orElseThrow(() -> new BusinessException("查无此人"));

        List<ReportOutputVo> reportOutputVoList = Lists.newArrayList();
        List<SickAndUser> sickAndUser = sickUserDao.findAllByUserId(userId);
        if (CollectionUtils.isEmpty(sickAndUser)) {
            return reportOutputVoList;
        }
        List<Long> sickIds = sickAndUser.stream().map(u -> u.getSickId()).collect(Collectors.toList());
        Map<Long, SickAndUser> sickAndUserMap = sickAndUser.stream().collect(Collectors.toMap(SickAndUser::getSickId, Function.identity()));
        List<SickInfo> sickInfoList = sickInfoDao.findAllByIdIn(sickIds);
        if (CollectionUtils.isEmpty(sickInfoList)) {
            return reportOutputVoList;
        }
        for (SickInfo si : sickInfoList) {
            ReportOutputVo reportOutputVo = new ReportOutputVo();
            reportOutputVo.setId(si.getId());
            reportOutputVo.setName(si.getPatientName());
            reportOutputVo.setUserId(userId);
            reportOutputVo.setUserPhone(userInfo.getPhone());
            reportOutputVo.setReportPhone(si.getPatientPhone());
            reportOutputVo.setCreateTime(DateFormatUtils.format(si.getCreateTime(), Constants.YYYY_MM_DD_HH_MM_SS));
            reportOutputVo.setSickAndUserId(sickAndUserMap.get(si.getId()).getId());
            reportOutputVoList.add(reportOutputVo);
        }
        return reportOutputVoList;
    }

    public List<ReportOutputVo> findReportByPhone(String phone) {
        UserInfo userInfo = userInfoDao.findOneByPhone(phone);
        if (userInfo == null) {
            throw new BusinessException("查无此人");
        }
        return this.findReportById(userInfo.getId());
    }

    public void deleteSickAndUser(long id) {
        sickUserDao.deleteById(id);
    }

    public void clearUserInfo(long id) {
        UserInfo userInfo = userInfoDao.findById(id).orElseThrow(() -> new BusinessException("查无此人"));
        userInfoDao.save(userInfo);
        UserInfoDetail ud = userInfoDetailDao.findOneByUserId(id);
        if (ud != null) {
            ud.setHeadIcon("");
            ud.setAddress("");
            ud.setAllergyInfo("");
            ud.setFamilyInfo("");
            ud.setHistoryInfo("");
            ud.setIdNumber("");
            ud.setOperationInfo("");
            ud.setSocialId("");
            ud.setMarryInfo("");
            ud.setTasteInfo("");
            userInfoDetailDao.save(ud);
        }
    }
}
